﻿using System.Collections;

namespace SableCC15
{
    /// <summary>
    /// This is the base type of the SymbolTableEntry.. Every Entry should derive from this class!
    /// </summary>
    public abstract class SymbolTableEntry
    {
        protected string scope;
        protected string id;

        /// <summary>
        /// Override tostring method to show proper details about the object!
        /// </summary>
        /// <returns>The id of the entry</returns>
        public override string ToString()
        {
            return "The ID : " + id + " " + "The Scope: " + scope;
        }
    }

    /// <summary>
    /// An entry for Variable symbols
    /// </summary>
    public class VariableEntry : SymbolTableEntry
    {
        /// <summary>
        /// The queue for the parameters.
        /// </summary>
        private Queue _paramQueue = new Queue();
        /// <summary>
        /// So we can reset the parameter check
        /// </summary>
        private Queue _paramHolder = new Queue();
        private bool _isDrawFunc = false; private bool _isListFunc = false;

        /// <summary>
        /// Initializes a new instance of VariableEntry class.
        /// </summary>
        public VariableEntry()
        { }

        /// <summary>
        /// Initializes a new instance of VariableEntry class.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="scope"></param>
        /// <param name="scopelevel"></param>
        /// <param name="datatype"></param>
        public VariableEntry(string name, string scope, int scopelevel, string datatype)
        {
            this.id = name;
            this.scope = scope;
            this.ScopeLevel = scopelevel;
            this.DataType = datatype;
        }
        /// <summary>
        /// Get and sets the indication whether it is a draw function or not
        /// </summary>
        public bool IsDrawFunction { get { return _isDrawFunc; } set { _isDrawFunc = value; } }

        /// <summary>
        /// Get and sets the indication whether it is a List function or not
        /// </summary>
        public bool IsListFunction { get { return _isListFunc; } set { _isListFunc = value; } }

        /// <summary>
        /// Gets and Sets the numeric value for the variable
        /// </summary>
        public bool NumericValue { get; set; }

        /// <summary>
        /// Gets and sets the scope of the variable
        /// </summary>
        public string Scope { get { return base.scope; } set { base.scope = value; } }

        /// <summary>
        /// Get and Sets the name/Id of the variable
        /// </summary>
        public string Id { get { return base.id; } set { base.id = value; } }

        /// <summary>
        /// Get and sets the level of scope 
        /// </summary>
        public int ScopeLevel { get; set; }

        /// <summary>
        /// Gets and sets the datatype
        /// </summary>
        public string DataType { get; set; }

        /// <summary>
        /// Gets The count of the queue
        /// </summary>
        public int ParamQueueCount { get { return _paramQueue.Count; } }

        public int ParamCount { get { return _paramQueue.Count + _paramHolder.Count; } }

        /// <summary>
        /// Enqueues the variable Entry.
        /// </summary>
        /// <param name="ve"></param>
        /// <returns></returns>
        public bool ParamEnqueue(VariableEntry ve)
        {
            if (this.DataType == "function")
            {
                _paramQueue.Enqueue(ve);
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// Removes and returns the Variable entry from the queue.
        /// </summary>
        /// <returns></returns>
        public VariableEntry ParamDequeue(bool toReplace)
        {
            VariableEntry ve = (VariableEntry)_paramQueue.Dequeue();
            if (!toReplace)
                _paramHolder.Enqueue(ve);
            return ve;
        }

        public VariableEntry ParamPeek()
        {
            return (VariableEntry)_paramQueue.Peek();
        }

        /// <summary>
        /// Checks if the paramter exists inside the queue.
        /// </summary>
        /// <param name="ve"></param>
        /// <returns></returns>
        public bool VarParamIdExists(VariableEntry ve)
        {
            Queue temp = new Queue();
            while (_paramQueue.Count != 0)
            {
                VariableEntry paramVe = (VariableEntry)_paramQueue.Dequeue();
                if (paramVe.Id == ve.Id)
                {
                    while (temp.Count != 0)
                    {
                        _paramQueue.Enqueue(temp.Dequeue());
                    }
                    return true;
                }
                temp.Enqueue(paramVe);
            }
            while (temp.Count != 0)
            {
                _paramQueue.Enqueue(temp.Dequeue());
            }
            return false;
        }

        /// <summary>
        /// To allow for multiple calls to the same function we need to reset the parameter queue each time
        /// </summary>
        public void ParamReset()
        {
            while (_paramHolder.Count != 0)
                _paramQueue.Enqueue(_paramHolder.Dequeue());
        }
    }
}
